package com.fili;

/**
 * Created by Claudiu-Florin FILIMON
 * Date: Nov 2, 2006
 * Time: 1:08:29 PM
 * Revision: 0
 */

import com.fili.resources.texture.Texture;
import com.fili.resources.texture.TextureFactory;
import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;

/**
 * Basic game
 *
 * @author Name <email>
 * @version 1.0
 */
public class Game
{

    /**
     * Game title
     */
    public static final String GAME_TITLE = "My Game";

    /**
     * Desired frame time
     */
    private static final int FRAMERATE = 60;

    /**
     * Exit the game
     */
    private static boolean finished;

    /**
     * Angle of rotating square
     */
    private static float angle;
    private static Texture tex;
    private static long lastTime=System.currentTimeMillis();
    private static long frameCount=0;

    /**
     * Application init
     *
     * @param args Commandline args
     */
    public static void main(String[] args)
    {
        boolean fullscreen = (args.length == 1 && args[0].equals("-fullscreen"));

        try
        {
            init(fullscreen);
            tex = TextureFactory.getTexture("res/tex.png");
            run();
        }
        catch (Exception e)
        {
            e.printStackTrace(System.err);
            Sys.alert(GAME_TITLE, "An error occured and the game will exit.");
        }
        finally
        {
            cleanup();
        }
        System.exit(0);
    }

    /**
     * Initialise the game
     *
     * @throws Exception if init fails
     */
    private static void init(boolean fullscreen) throws Exception
    {
        // Create a fullscreen window with 1:1 orthographic 2D projection (default)
        Display.setTitle(GAME_TITLE);

        DisplayMode mode = null;
        for (DisplayMode dm : Display.getAvailableDisplayModes())
        {
//            System.out.println(dm.getWidth()+"x"+dm.getHeight()+"x"+dm.getBitsPerPixel()+"@"+dm.getFrequency());
            if ((dm.getWidth() == 640) && (dm.getHeight() == 480))
                mode = dm;
        }
        Display.setDisplayMode(mode);

        Display.setFullscreen(fullscreen);
        // Enable vsync if we can (due to how OpenGL works, it cannot be guarenteed to always work)
        Display.setVSyncEnabled(false);
        // Create display
        Display.create();
    }

    /**
     * Runs the game (the "main loop")
     */
    private static void run()
    {
        while (!finished)
        {
            // Always call Window.update(), all the time - it does some behind the
            // scenes work, and also displays the rendered output
            Display.update();

            // Check for close requests
            if (Display.isCloseRequested())
            {
                finished = true;
            }

            // The window is in the foreground, so we should play the game
            else
                if (Display.isActive())
                {
                    logic();
                    render();
                    frameCount++;
                    long t = System.currentTimeMillis();
                    if (t-lastTime>=1000)
                    {
                        Display.setTitle("FPS: "+(frameCount*1000f/(t-lastTime)));
                        lastTime = t;
                        frameCount = 0;
                    }
//                    Display.sync(FRAMERATE);
                }

                // The window is not in the foreground, so we can allow other stuff to run and
                // infrequently update
                else
                {
                    try
                    {
                        Thread.sleep(100);
                    }
                    catch (InterruptedException e)
                    {
                    }
                    logic();

                    // Only bother rendering if the window is visible or dirty
                    if (Display.isVisible() || Display.isDirty())
                    {
                        render();
                    }
                }
        }
    }

    /**
     * Do any game-specific cleanup
     */
    private static void cleanup()
    {
        // Close the window
        Display.destroy();
        Keyboard.destroy();
    }

    /**
     * Do all calculations, handle input, etc.
     */
    private static void logic()
    {
        // Example input handler: we'll check for the ESC key and finish the game instantly when it's pressed
        if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE))
        {
            finished = true;
        }

        // Rotate the square
        angle += .50f % 360;
    }

    /**
     * Render the current frame
     */
    private static void render()
    {
        // clear the screen
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT);

        // center square according to screen size
        GL11.glPushMatrix();
        GL11.glTranslatef(Display.getDisplayMode().getWidth() / 2, Display.getDisplayMode().getHeight() / 2, 0.0f);

        // rotate square according to angle
        GL11.glRotatef(angle, 0, 0, 1.0f);

        GL11.glEnable(GL11.GL_TEXTURE_2D);
//        GL11.glColor4f(1.0f, 1.0f, 1.0f, 0.5f);
        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
        GL11.glEnable(GL11.GL_BLEND);
        // render the square
        tex.bind(GL11.GL_TEXTURE_2D);
        GL11.glBegin(GL11.GL_QUADS);
        GL11.glTexCoord2f(0, 0);
        GL11.glVertex2i(-50, -50);
        GL11.glTexCoord2f(1, 0);
        GL11.glVertex2i(50, -50);
        GL11.glTexCoord2f(1, 1);
        GL11.glVertex2i(50, 50);
        GL11.glTexCoord2f(0, 1);
        GL11.glVertex2i(-50, 50);
        GL11.glEnd();

        GL11.glPopMatrix();
    }
}